package com.game.modular.game.match.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.game.comment.exection.InfoTips;
import com.game.modular.game.battle.info.base.PvpPlayerInfo;
import com.game.modular.game.battle.info.base.PvpPlayerInfoServiceImpl;
import com.game.modular.game.match.domain.PvpMatchEnd;
import com.game.modular.game.match.service.base.PvpMatchEndBaseServiceImpl;
import com.game.modular.game.playerAssets.service.PlayerBagServiceImpl;
import com.game.modular.game.playerAssets.service.PlayerHeroServiceImpl;
import com.game.modular.game.playerInfo.domain.PlayerMatch;
import com.game.modular.game.playerMatch.service.*;
import com.game.modular.game.playerInfo.service.PlayerRankServiceImpl;
import com.game.modular.game.playerMatch.domain.PvpMatch;
import com.game.modular.gameCore.match.service.impl.CoreMatchEndExpServiceImpl;
import com.game.modular.gameCore.match.service.impl.CoreMatchEndIntegralServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * pvp对局信息(PvpMatchEnd)表服务实现类
 *
 * @author cxy
 * @since 2024-09-09 11:57:21
 */
@Slf4j
@Service
@RequiredArgsConstructor

public class PvpMatchEndServiceImpl extends PvpMatchEndBaseServiceImpl {
    @Value(value = "${match.end.time}")
    private int matchEndTime;
    @Value(value = "${match.exit.time}")
    private int matchExitTime;
    @Resource
    private CoreMatchEndExpServiceImpl coreMatchEndExpService;
    @Resource
    private PvpMatchServiceImpl pvpMatchServiceImpl;
    @Resource
    private PlayerRankServiceImpl playerRankServiceImpl;
    @Resource
    private CoreMatchEndIntegralServiceImpl coreMatchEndIntegralServiceImpl;
    @Resource
    private PvpPlayerInfoServiceImpl pvpPlayerInfoServiceImpl;
    @Resource
    private PvpMatchServiceImpl pvpMatchService;
    @Resource
    private PlayerMatchServiceImpl playerMatchService;
    @Resource
    private PvpPlayerInfoServiceImpl playerInfoService;
    @Resource
    private PvpCityServiceImpl pvpCityServiceImpl;
    @Resource
    private PlayerBagServiceImpl playerBagServiceImpl;
    @Resource
    private PvpRanksServiceImpl pvpRanksService;
    @Resource
    private PlayerHeroServiceImpl playerHeroServiceImpl;
    @Resource
    private PvpMatchEndExpServiceImpl pvpMatchEndExpService;
    @Resource
    private PvpMatchEndWinPointServiceImpl pvpMatchEndIntegralService;
    @Resource
    private PvpNpcRanksServiceImpl pvpNpcRanksServiceImpl;
    @Resource
    private PlayerMatchServiceImpl playerMatchServiceImpl;

    /**
     * 初始化结算信息
     */
    private void init(Long matchId, Long playerId) {
        PvpPlayerInfo loserInfo = pvpPlayerInfoServiceImpl.get(matchId, playerId);
        PvpMatchEnd build = PvpMatchEnd.builder()
                .matchId(loserInfo.getMatchId())
                .playerId(loserInfo.getPlayerId())
                .eliminatePlayers(loserInfo.getKilledPlayers().size())
                .citiesQuantity(loserInfo.getCurrentCity().size())
                .ranking(loserInfo.getRanking())
                .isRuler(loserInfo.getIsRuler())
                .killedBy(loserInfo.getKilledBy())
                .build();
        save(build);
    }


    /**
     * 退出|结算-经验,积分
     */
    @Transactional
    public void exitGame(Long playerId, Long matchId) {
        PvpPlayerInfo pvpPlayerInfo = pvpPlayerInfoServiceImpl.get(matchId, playerId);
        pvpPlayerInfo.setIsExit(1);
        pvpPlayerInfoServiceImpl.update(pvpPlayerInfo);
        PvpPlayerInfo loserInfo = pvpPlayerInfoServiceImpl.get(matchId, playerId);
        if (loserInfo.getSurvivalTime() < matchExitTime) {
                throw new InfoTips("玩家存活时间太短,无法结算");
        }
        init(matchId, playerId);
        pvpMatchEndExpService.obtainExpReward(matchId, playerId);
        pvpMatchEndIntegralService.obtainIntegralReward(matchId, playerId);
        ////////////////////////////////////////////////////////////////////////////////////////////////////  玩家退出对局
        playerBagServiceImpl.resetPvp(playerId);
        pvpRanksService.resetPvp(playerId);
        playerMatchService.resetPvp(playerId);
        pvpMatchService.resetPvp(matchId, playerId);
        pvpCityServiceImpl.clearAllPlayerCities(loserInfo);
    }

    /**
     * 尝试武力结束
     */
    @Transactional
    public void tryMilitaryConquestSettlement(Long matchId) {
        pvpPlayerInfoServiceImpl.statisticalRanking(matchId);
        // 检查比赛是否存在
        PvpMatch pvpMatch = pvpMatchServiceImpl.getById(matchId);
        if (pvpMatch == null) {
            throw new IllegalArgumentException("比赛不存在: " + matchId);
        }
        if (pvpMatch.getStatus()==2){
            return;
        }

        List<PvpPlayerInfo> list = pvpPlayerInfoServiceImpl.listCache(matchId);
        // 退出死亡的玩家
        List<PvpPlayerInfo> deadNeedExit =
                list.stream().filter(item -> item.getIsDead() == 1 && item.getIsExit() == 0).collect(Collectors.toList());
        for (PvpPlayerInfo pvpPlayerInfo : deadNeedExit) {
            exitGame(pvpPlayerInfo.getPlayerId(), matchId);
        }

        // 胜利则清除所有存活的玩家
        List<PvpPlayerInfo> winnerlList = pvpPlayerInfoServiceImpl.obtainWinnerlList(matchId);
        // 有联盟获取胜利
        boolean b = winnerlList != null && !winnerlList.isEmpty();

        if (b) {
            List<PvpPlayerInfo> needExit = list.stream()
                    .filter(item -> item.getIsDead() == 0 && item.getIsExit() == 0)
                    .collect(Collectors.toList());
            for (PvpPlayerInfo pvpPlayerInfo : needExit) {
                exitGame(pvpPlayerInfo.getPlayerId(), matchId);
            }
            endGame(matchId);
        }
    }


    @Transactional
    public void tryWorldSettlement(Long matchId) {
        pvpPlayerInfoServiceImpl.statisticalRanking(matchId);

        PvpMatch pvpMatch = pvpMatchServiceImpl.getById(matchId);
        if (pvpMatch == null) {
            pvpMatchServiceImpl.exitMatchHeart(matchId);
            return;
        }
        if (pvpMatch.getStatus()==2){

            pvpMatchServiceImpl.exitMatchHeart(matchId);
            return;
        }
        Date startTime = pvpMatch.getStartTime();

        // 检查时间是否已到
        Duration duration = Duration.between(startTime.toInstant(), Instant.now());
        boolean hasMatchEnded = duration.toMillis() > matchEndTime;
        if (hasMatchEnded) {// 退出所有没有退出的
            List<PvpPlayerInfo> needExit = pvpPlayerInfoServiceImpl.listCache(matchId).stream()
                    .filter(item -> item.getIsExit() == 0)
                    .collect(Collectors.toList());
            for (PvpPlayerInfo pvpPlayerInfo : needExit) {
                exitGame(pvpPlayerInfo.getPlayerId(), matchId);
            }
            endGame(matchId);
            return;
        }

        // 查看是否统治结束
        List<PvpPlayerInfo> collect = pvpPlayerInfoServiceImpl.listCache(matchId).stream()
                .filter(item -> item.getIsRuler() == 1)
                .collect(Collectors.toList());
        if (!collect.isEmpty()){
            for (PvpPlayerInfo pvpPlayerInfo : collect) {
                exitGame(pvpPlayerInfo.getPlayerId(), matchId);
                endGame(matchId);
                return;
            }
        }
    }


    /**
     * 结束游戏
     *
     * @param matchId 对局id
     */
    @Transactional
    public void endGame(Long matchId) {
        PvpMatch pvpMatch = pvpMatchServiceImpl.getById(matchId);
        List<PlayerMatch> list = playerMatchServiceImpl.list(new LambdaQueryWrapper<PlayerMatch>()
                .eq(PlayerMatch::getCurrentMatchId, matchId)
                .ne(PlayerMatch::getCurrentMatchId, 0)
        );

        if (list!=null){
            for (PlayerMatch playerMatch : list) {
                if (Objects.equals(pvpMatch.getId(), playerMatch.getCurrentMatchId())){
                    playerMatch.setCurrentMatchId(0L);
                    playerMatchServiceImpl.updateById(playerMatch);
                }
            }
        }

        pvpMatch.setEndTime(new Date());
        pvpMatch.setStatus(2);
        pvpMatchServiceImpl.updateById(pvpMatch);

        pvpMatchServiceImpl.exitMatchHeart(matchId);
    }
}
